package cn.com.bluemoon.daps.standard.controller;


import cn.com.bluemoon.common.security.BmDapConfig;
import cn.com.bluemoon.daps.common.constant.DapConstant.DapStandard.StandardType;
import cn.com.bluemoon.daps.common.datascope.BmPermission;
import cn.com.bluemoon.daps.common.domain.ResultBean;
import cn.com.bluemoon.daps.common.domain.UserInfoHolder;
import cn.com.bluemoon.daps.common.exception.DapException;
import cn.com.bluemoon.daps.common.exception.DapThrowException;
import cn.com.bluemoon.daps.common.mp.IBmService;
import cn.com.bluemoon.daps.common.toolkit.BmAssetUtils;
import cn.com.bluemoon.daps.common.toolkit.WebDownloadUtils;
import cn.com.bluemoon.daps.common.webhook.Authors;
import cn.com.bluemoon.daps.standard.dto.AddCheck;
import cn.com.bluemoon.daps.standard.dto.UpdateCheck;
import cn.com.bluemoon.daps.standard.entity.DapStandardIndex;
import cn.com.bluemoon.daps.standard.service.DapStandardIndexService;
import cn.com.bluemoon.daps.standard.service.DapStandardModifyService;
import cn.com.bluemoon.daps.standard.vo.BasicStandardAndDicVo;
import cn.com.bluemoon.daps.standard.vo.IndexStandardVo;
import cn.com.bluemoon.daps.standard.vo.StandardDataModifyVo;
import cn.com.bluemoon.daps.standard.vo.StandardListSearchVo;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

/**
 * <p>
 * 数据标准的核心表，记录各标准的版本和审核状态 前端控制器
 * </p>
 * 审核列表
 * 变更列表
 * 基础标准crud
 * 指标标准crud
 * 批量导入
 *
 * @author admin
 * @since 2020-08-07
 */
@Api(tags = "标准变更列表")
@RestController
@Slf4j
@Authors(value = @Authors.Author(name = "Jarod.Kong", desc = "标准变更列表", devTime = ""))
@RequestMapping("/dapStandardModify")
public class DapStandardModifyController {

    public static final String INDEX_FILENAME = "指标标准导入模板.xlsx";
    public static final String BASIC_FILENAME = "基础标准导入模板.xlsx";

    @Autowired
    private DapStandardModifyService dapStandardModifyService;
    @Autowired
    private DapStandardIndexService dapStandardIndexService;
    @Resource
    private BmDapConfig bmDapConfig;

    @BmPermission(value = {"standard:modify:basic:query", "standard:modify:index:query"}, name = "标准变更查询")
    @PostMapping("/modify/list")
    @ApiOperation(value = "根据查询条件获取变更列表数据")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = StandardDataModifyVo.class)})
    public ResultBean<?> modifyList(@RequestBody @Valid StandardListSearchVo<?> standardListSearchVo) {
        IPage<StandardDataModifyVo> standardDataModifyVoPage = dapStandardModifyService.modifyList(standardListSearchVo);
        return IBmService.toAntDvPageTool(standardDataModifyVoPage);
    }

    @BmPermission(value = {"standard:modify:basic:add"}, name = "标准变更-基础标准新增")
    @PostMapping("/basicStandard")
    @ApiOperation(value = "保存基础标准数据和字典，返回标准id")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    public ResultBean<String> basicAdd(@RequestBody @Validated(value = {AddCheck.class})
                                               BasicStandardAndDicVo basicStandardAndDicVo) {
        String standardId = dapStandardModifyService.saveStandardBasicAndDicAndAudit(basicStandardAndDicVo);
        return ResultBean.ok(standardId);
    }

    @BmPermission(value = {"standard:modify:index:add"}, name = "标准变更-指标标准新增")
    @PostMapping("/indexStandard")
    @ApiOperation(value = "保存指标标准数据和字典，返回标准id")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    public ResultBean<String> indexAdd(@RequestBody @Validated
                                               IndexStandardVo indexStandardVo) {
        String standardId = dapStandardModifyService.saveStandardIndexAndAudit(indexStandardVo);
        return ResultBean.ok(standardId);
    }

    @BmPermission(value = {"standard:modify:basic:view", "standard:query:basic:view"}, name = "标准变更-基础标准查看")
    @GetMapping("/basicStandard/{id}")
    @ApiOperation(value = "根据标准id获取标准数据和标准字典数据")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = BasicStandardAndDicVo.class)})
    public ResultBean<BasicStandardAndDicVo> basicGet(@PathVariable String id) {
        BasicStandardAndDicVo basicStandardAndDicVo = dapStandardModifyService.getBasicStandardAndDicVo(id);
        return ResultBean.ok(basicStandardAndDicVo);
    }

    @BmPermission(value = {"standard:modify:index:view", "standard:query:index:view"}, name = "标准变更-指标标准查看")
    @GetMapping("/indexStandard/{id}")
    @ApiOperation(value = "根据标准id获取标准数据和标准字典数据")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    public ResultBean<DapStandardIndex> indexGet(@PathVariable String id) {
        DapStandardIndex standardIndex = dapStandardIndexService.getById(id);
        return ResultBean.ok(standardIndex);
    }

    @BmPermission(value = {"standard:modify:basic:edit"}, name = "标准变更-基础标准编辑")
    @PutMapping("/basicStandard/{id}")
    @ApiOperation(value = "保存编辑的基础标准数据和字典，返回编辑的标准id")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    public ResultBean<String> basicEdit(@RequestBody @Validated(value = {UpdateCheck.class}) BasicStandardAndDicVo basicStandardAndDicVo,
                                        @PathVariable("id") String id) {
        String editBasicStandardId = dapStandardModifyService.editBasicStandardAndDicAndAudit(basicStandardAndDicVo, id);
        return ResultBean.ok(editBasicStandardId);
    }

    @BmPermission(value = {"standard:modify:index:edit"}, name = "标准变更-指标标准编辑")
    @PutMapping("/indexStandard/{standardIndexId}")
    @ApiOperation(value = "保存指标标准数据和字典，返回标准id")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    public ResultBean<String> indexEdit(@RequestBody @Validated DapStandardIndex dapStandardIndex,
                                        @PathVariable("standardIndexId") String standardIndexId) {
        String standardId = dapStandardModifyService.editIndexStandardAndAudit(dapStandardIndex, standardIndexId);
        return ResultBean.ok(standardId);
    }

    @BmPermission(value = {"standard:modify:index:startAudit", "standard:modify:basic:startAudit"}, name = "标准变更-标准发起审批")
    @PutMapping("/startAudit/{id}")
    @ApiOperation(value = "根据流程id进行发起审批里流程")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    public ResultBean<?> startAudit(@PathVariable String id) {
        dapStandardModifyService.startAudit(id);
        return ResultBean.ok();
    }

    @BmPermission(value = {"standard:modify:index:startAudit", "standard:modify:basic:startAudit"}, name = "标准变更-标准发起审批")
    @PutMapping("/startAuditBatch")
    @ApiOperation(value = "根据流程id进行批量发起审批里流程")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    public ResultBean<?> startAuditBatch(@RequestBody List<String> ids) {
        //noinspection AliControlFlowStatementWithoutBraces
        if (ids == null) {
            ids = Collections.emptyList();
        }
        dapStandardModifyService.startAudit(ids.toArray(new String[0]));
        return ResultBean.ok();
    }

    @BmPermission(value = {"standard:modify:index:revert", "standard:modify:basic:revert"}, name = "标准变更-标准撤销")
    @PutMapping("/revert/{id}")
    @ApiOperation(value = "根据流程id进行撤销待审批流程")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    public ResultBean<?> basicRevert(@PathVariable String id) {
        // 标准类型通过id 获取
        dapStandardModifyService.revertAudit(id);
        return ResultBean.ok();
    }

    @BmPermission(value = {"standard:modify:basic:import", "standard:modify:index:import"},
            name = "标准变更-标准下载", queryTokenPerm = true)
    @ApiOperation(value = "下载文件")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "正常返回", response = Void.class)})
    @GetMapping("/download")
    public void download(HttpServletResponse response, @ApiParam("标准类型 0 为基础标准  1为指标标准") @RequestParam String standardType) {
        String filename = !"0".equals(standardType) ? INDEX_FILENAME : BASIC_FILENAME;
        try (InputStream in = this.getClass().getClassLoader().getResourceAsStream("download/" + filename)) {
            WebDownloadUtils.commonDownload(response, in, filename);
        } catch (IOException e) {
            log.error("下载文件流异常", e);
        }
    }

    @BmPermission(value = {"standard:modify:basic:import", "standard:modify:index:import"}, name = "标准变更-标准导入", queryTokenPerm = true)
    @PostMapping("/standard/import")
    @ApiOperation(value = "上传标准文件导入")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    public ResultBean<?> fileImport(@RequestParam("file") MultipartFile file,
                                    @RequestParam("standardType") Integer standardType) {
        log.info("获取上传文件：{}, 标准类型为：{}", file == null ? null : file.getOriginalFilename(), StandardType.BASIC.getCode() == standardType ? "基础" : "指标");
        BmAssetUtils.isFalse(file == null || (file.getOriginalFilename() == null), () -> new DapThrowException("获取上传文件为空"));
        String originalFilename = file.getOriginalFilename();
        List<String> standardAllowSuffix = bmDapConfig.getFile().getStandardAllowSuffix();
        boolean isMatch = standardAllowSuffix.stream().anyMatch(originalFilename::endsWith);
        BmAssetUtils.isTrue(isMatch, () -> new DapThrowException("当前文件类型" + originalFilename.substring(originalFilename.lastIndexOf('.')) + "不符合：" + standardAllowSuffix));
        // 针对上传的文件保存一份到服务器 是否考虑保存时长
        Optional<String> saveFilePath = dapStandardModifyService.storeUploadFile(file, originalFilename);
        try (InputStream inputStream = file.getInputStream()) {
            // 导入
            if (saveFilePath.isPresent()) {
                return dapStandardModifyService.fileImport(saveFilePath.get(), standardType);
            } else {
                return dapStandardModifyService.fileImport(inputStream, file, standardType);
            }
        } catch (IOException e) {
            log.error("处理文件失败", e);
            return ResultBean.ok(e.getMessage());
        }
    }


    @BmPermission(value = {"standard:modify:basic:import", "standard:modify:index:import"},
            name = "标准变更-标准下载", queryTokenPerm = true)
    @ApiOperation(value = "下载文件")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "正常返回", response = Void.class)})
    @GetMapping("/download/index/v2")
    public void downloadV2(HttpServletResponse response) {
        String filename = "指标标准导入模板v2.xlsx";
        try (InputStream in = this.getClass().getClassLoader().getResourceAsStream("download/" + filename)) {
            WebDownloadUtils.commonDownload(response, in, filename);
        } catch (IOException e) {
            log.error("下载文件流异常", e);
        }
    }

    @BmPermission(value = {"standard:modify:basic:import", "standard:modify:index:import"}, name = "标准变更-标准导入", queryTokenPerm = true)
    @PostMapping("/standard/import/v2")
    @ApiOperation(value = "上传标准文件导入")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    public ResultBean<?> fileImportV2(@RequestParam("file") MultipartFile file,
                                      @ApiParam(value = "标准类型：1 指标标准", defaultValue = "1")
                                      @RequestParam(value = "standardType", defaultValue = "1") Integer standardType,
                                      @ApiParam("业务线id")
                                      @RequestParam("bizLineId") Integer bizLineId) {
        if (1 != standardType) {
            throw new DapException("新版模板导入只支持指标标准!");
        }
        BmAssetUtils.isFalse(file == null || (file.getOriginalFilename() == null), () -> new DapThrowException("获取上传文件为空"));
        try (InputStream inputStream = file.getInputStream()) {
            return dapStandardModifyService.fileImportV2(inputStream, file, standardType, bizLineId, UserInfoHolder.getUserInfoOrEmpty());
        } catch (IOException e) {
            log.error("处理文件失败", e);
            return ResultBean.ok(e.getMessage());
        }
    }
}
